package com.feihong.activity.service.impl;

import com.feihong.activity.entity.EquipmentRequest;
import com.feihong.activity.entity.*;
import com.feihong.activity.enums.CustomExceptionEnum;
import com.feihong.activity.enums.SensorEnum;
import com.feihong.activity.exception.CustomException;
import com.feihong.activity.mapper.FeedingAreaMapper;
import com.feihong.activity.mapper.PushCityMapper;
import com.feihong.activity.service.PushCityService;
import com.feihong.activity.service.ThirdPartyService;
import com.feihong.activity.vo.PushVo;
import com.feihong.activity.vo.PushVos;
import com.feihong.common.service.DefaultServiceImpl;
import com.feihong.common.util.FileUtils;
import com.feihong.common.util.JsonObjectUtils;
import com.feihong.common.util.StringOurUtils;
import com.feihong.common.util.UUIDGenerator;
import io.swagger.models.auth.In;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.swing.text.StyledEditorKit;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PushCityServiceImpl extends DefaultServiceImpl implements PushCityService {
    @Resource
    private PushCityMapper pushCityMapper;
    @Resource
    private FeedingAreaMapper feedingAreaMapper;
    @Resource
    private AuthDemo auth;
    @Resource
    private AreaInfo area;
    @Resource
    private ThirdPartyService thirdPartyService;


    @Override
    public void pushInfoByArea(PushVo pushVO) throws IllegalAccessException {
        //查看该产品是否有设备存在，没有设备则返回异常
        Integer count = pushCityMapper.selectSensorCountByAreaDataCode(pushVO.getAreaDataCode());
        if (count == null || count == 0) {
            throw new CustomException(CustomExceptionEnum.NO_SUCH_SENSOR_EXCEPTION);
        }
        pushCityMapper.addPushTask(pushVO.getProductName(), auth.getUrl());
        Integer taskId = getMaxTaskId();
        //开始验证设置
        addAuthentication(taskId);
        pushCityMapper.addRequestHeader(taskId);
        //构建sensor对象以建立推送字段表
        Sensor sensor = new Sensor();
        sensor.setDataCode(pushVO.getCityDataCode());
        sensor.setPostTime("TIME");
        buildField(taskId, sensor);

        pushCityMapper.addPushRange(taskId, pushVO.getAreaDataCode());
    }

    private void buildField(Integer newTaskId, Sensor sensor) throws IllegalAccessException {
        Field[] declaredFields = sensor.getClass().getDeclaredFields();
        List<SensorDTO> list = new ArrayList<>();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            SensorDTO sensorDTO = new SensorDTO();
            sensorDTO.setField(declaredField.getName());
            sensorDTO.setValue((String) declaredField.get(sensor));
            sensorDTO.setUnderField(StringOurUtils.camel2under(declaredField.getName()));
            sensorDTO.setNewTaskId(newTaskId);

            if ("dataCode".equals(declaredField.getName())) {
                sensorDTO.setUnderField("product_key");
            }
//            else if("sensorType".equals(declaredField.getName())){
//
//            }
            list.add(sensorDTO);
        }
        if (list.size() != 0) {
            pushCityMapper.addFieldReplace(list);
        }
    }

    @Override
    public void pushAllByArea(String pathName,String batchName) throws IllegalAccessException, IOException {

        List<Integer> a = pushCityMapper.selectAreaDataCodesCountByArea();

        pushCityMapper.addPushTask(batchName, auth.getUrl());
        Integer taskId = getMaxTaskId();
        addAuthentication(taskId);
        pushCityMapper.addRequestHeader(taskId);
        Map<String, String> map = FileUtils.getMap(pathName,taskId);
        pushCityMapper.addPushRangeFieldRel(taskId, map);
        Sensor sensor = new Sensor();
        sensor.setDataCode("REL");
        sensor.setPostTime("TIME");
        buildField(taskId, sensor);
        pushCityMapper.addAll(taskId);
    }

    @Override
    public String upload(MultipartFile file) throws IOException {
        String url = "";
        //上传最大为10MB
        int maxSize = 1024 * 1024 * 10;
        File targetFile = null;
//        if (file.getSize() > maxSize) {
//            throw new CustomException(CustomExceptionEnum.FILE_SIZE_EXCEEDS_MAXIMUM);
//        }
        //获取文件名加后缀
        String fileName = file.getOriginalFilename();
        if (fileName != null && !fileName.equals("")) {
            String path = new File("").getCanonicalPath() + "\\temp";
            //文件后缀
            String suffix = fileName.substring(fileName.lastIndexOf("."));
//            if (!(suffix.equals(".xlsx") || suffix.equals(".xls") || suffix.equals(".docx") || suffix.equals(".doc"))) {
//                throw new CustomException(CustomExceptionEnum.FORMAT_UPLOAD_ERROR);
//            }
            //新的文件名
            String uuid = UUIDGenerator.getUUID();
            fileName = uuid + suffix;
            //获取文件夹路径
            File file1 = new File(path);
            //如果文件夹不存在则创建
            if (!file1.exists() && !file1.isDirectory()) {
                file1.mkdirs();
            }
            //将文件存入文件夹
            targetFile = new File(file1, fileName);
            try {
                //将上传的文件写到服务器上指定的文件。
                file.transferTo(targetFile);
                //生成文件地址
                url = path + "\\" + fileName;
                logger.info("数据上传成功，url： " + url);
            } catch (Exception e) {
                e.printStackTrace();

            }
        }

        return url;
    }

    //no complete
    @Override
    public String importFileByPath(String pathName, SensorEnum sensorEnum) throws Exception {
        List<Sensor> sensors = new ArrayList<>();
        File file = new File(pathName);
        if (!file.exists() || file.isDirectory()) {
            throw new CustomException("文件未找到");
        }
        XSSFWorkbook workbook = new XSSFWorkbook(pathName);
        XSSFSheet sheet = workbook.getSheetAt(0);
        int lastRowNum = sheet.getLastRowNum();
        logger.debug("该工作表共有" + lastRowNum + "行数据");
        for (int i = 1; i <= lastRowNum; i++) {
            XSSFRow cells = sheet.getRow(i);

            Sensor sensor = new Sensor();
            cells.getCell(0).setCellType(CellType.STRING);
            sensor.setSensorId(cells.getCell(0).getStringCellValue());
            cells.getCell(1).setCellType(CellType.STRING);
            sensor.setSensorName(cells.getCell(1).getStringCellValue());
            cells.getCell(2).setCellType(CellType.STRING);
            sensor.setSensorType(cells.getCell(2).getStringCellValue());
            cells.getCell(3).setCellType(CellType.STRING);
            sensor.setDataCode(cells.getCell(3).getStringCellValue());
            cells.getCell(4).setCellType(CellType.STRING);
            sensor.setApplyId(cells.getCell(4).getStringCellValue());
            cells.getCell(5).setCellType(CellType.STRING);
            sensor.setProjectCode(cells.getCell(5).getStringCellValue());
            cells.getCell(6).setCellType(CellType.STRING);
            sensor.setCityId(cells.getCell(6).getStringCellValue());
            cells.getCell(7).setCellType(CellType.STRING);
            sensor.setAreaId(cells.getCell(7).getStringCellValue());
            cells.getCell(8).setCellType(CellType.STRING);
            sensor.setRegionId(cells.getCell(8).getStringCellValue());
            cells.getCell(9).setCellType(CellType.STRING);
            sensor.setCommissionName(cells.getCell(9).getStringCellValue());
            cells.getCell(10).setCellType(CellType.STRING);
            sensor.setCommissionCode(cells.getCell(10).getStringCellValue());
            cells.getCell(11).setCellType(CellType.STRING);
            sensor.setAddress(cells.getCell(11).getStringCellValue());
            cells.getCell(12).setCellType(CellType.STRING);
            sensor.setWsLng(cells.getCell(12).getStringCellValue());
            cells.getCell(13).setCellType(CellType.STRING);
            sensor.setWsLat(cells.getCell(13).getStringCellValue());
            cells.getCell(14).setCellType(CellType.STRING);
            sensor.setConnectType(cells.getCell(14).getStringCellValue());

            sensor.setSaveType(sensorEnum.getCode());
            sensors.add(sensor);
        }
        workbook.close();
        String result = thirdPartyService.equipmentDataReporting(sensors);
        return result;
    }

    @Override
    public void importMappingByPath(String pathName) throws IOException {
        Map<String, String> maps = FileUtils.getMap(pathName,42);
        pushCityMapper.addPushProductKeyRel(42, maps);
    }



    @Override
    public void pushBaseInfoByFile(String equipmentPathName, String logPathName) throws Exception {
        File equipmentFile = new File(equipmentPathName);
        File logFile = new File(logPathName);
        if (!equipmentFile.exists() || equipmentFile.isDirectory()) {
            throw new CustomException("设备文件未找到");
        }
        if (!logFile.exists() || logFile.isDirectory()) {
            throw new CustomException("日志文件未找到");
        }

        List<EquipmentRequest> equipments = readAllByFile(equipmentFile, new EquipmentRequest());
        //过滤不需要的字段
        List<EquipmentRequest> transformedEquipments = filterEquipments(equipments);

        List<SensorLog> logs = readAllByFile(logFile, new SensorLog());
        List<EquipmentLog> transformedLogs = changeLogs(logs);

        Integer equipmentsCount = thirdPartyService.pushKafkaByList(equipments);
        Integer logsCount = thirdPartyService.pushKafkaByList(logs);
        logger.debug("设备共推送了"+equipmentsCount+"条");
        logger.debug("日志共推送了"+logsCount+"条");

    }



    private List<EquipmentLog> changeLogs(List<SensorLog> logs) {
        List<EquipmentLog> list = new ArrayList<>();
        for (SensorLog log : logs) {
            EquipmentLog equipmentLog = new EquipmentLog();
            Map<String ,String > filterData = new HashMap<>();
            for (String key : log.getData().keySet()) {
                if(key.equals("device_id")){
                    equipmentLog.setSensorId(log.getData().get(key));
                    continue;
                }
                filterData.put(key,log.getData().get(key));
            }
            equipmentLog.setData(filterData);
            equipmentLog.setDataCode(log.getDataCode());
            equipmentLog.setPostTime(log.getPostTime());
            list.add(equipmentLog);
        }
        return list;
    }

    private List filterEquipments(List<EquipmentRequest> equipments) {
        for (EquipmentRequest equipment : equipments) {
            Map<String, String> map = equipment.getEquipment();
            HashMap<String, String> filterMap = new HashMap<>();
            for (String field : map.keySet()) {
                if (field.equals("sensorId") || field.equals("sensorName") || field.equals("dataCode")) {
                    filterMap.put(field, map.get(field));
                }
            }
            equipment.setEquipment(filterMap);
        }
        return equipments;
    }

    private <T> List readAllByFile(File file, T t) throws Exception {
        InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
        BufferedReader br = new BufferedReader(isr);
        String json = br.readLine();
        List<T> list = new ArrayList<>();
        while (json != null) {
            T obj = (T) JsonObjectUtils.getObjectByString(json, t.getClass());
            list.add(obj);
            json = null;
//            json = br.readLine();
        }
        return list;
    }


    private void addAuthentication(Integer newTaskId) {
        pushCityMapper.addAuthentication(newTaskId, auth.getAuthUrl());

        String loginName = auth.getLoginName();
        pushCityMapper.addAuthUserName(loginName, newTaskId);
        String password = auth.getPassword();
        pushCityMapper.addAuthPassword(password, newTaskId);
        String platformId = auth.getPlatformId();
        pushCityMapper.addAuthPlatformId(platformId, newTaskId);

    }


    private Integer getMaxTaskId() {
        return pushCityMapper.getMaxTaskId();
    }

}
